package com.wfs.myapp.service.impl;

import com.wfs.myapp.config.MessageSendConfig;
import com.wfs.myapp.entity.domain.User;
import com.wfs.myapp.entity.domain.bk.BkBirthdayRemind;
import com.wfs.myapp.entity.domain.bk.BkSendMessage;
import com.wfs.myapp.entity.vo.OrderVo;
import com.wfs.myapp.enums.MessageStatusEnum;
import com.wfs.myapp.enums.OrderStatusEnum;
import com.wfs.myapp.enums.SearchTypeEnum;
import com.wfs.myapp.remote.wx.WxRemoteService;
import com.wfs.myapp.remote.wx.vo.SendMessageVo;
import com.wfs.myapp.repository.UserRepository;
import com.wfs.myapp.repository.bk.BirthdayRemindRepository;
import com.wfs.myapp.repository.bk.OrderRepository;
import com.wfs.myapp.repository.bk.SendMessageRepository;
import com.wfs.myapp.service.SchedualedService;
import com.wfs.myapp.utils.DateUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
@Slf4j
public class SchedualedServiceImpl implements SchedualedService {

    @Autowired
    private OrderRepository orderRepository;

    @Autowired
    private WxRemoteService remoteService;

    @Autowired
    private SendMessageRepository sendMessageRepository;

    @Autowired
    private BirthdayRemindRepository birthdayRemindRepository;

    @Autowired
    private UserRepository userRepository;

    @Override
    @Scheduled(cron = "0 0 */8 * * ?")
    public Void sendMessage() {
        List<BkSendMessage> byTypeAndAndStatus = sendMessageRepository.findByTypeAndStatus(SearchTypeEnum.ORDER.getCode(), MessageStatusEnum.UN_SEND.getCode());
        List<Long> orderIdList = byTypeAndAndStatus.stream().map(BkSendMessage::getTargetId).collect(Collectors.toList());
        List<Integer> statusList = Arrays.asList(OrderStatusEnum.APPROVE.getCode(), OrderStatusEnum.EXCEEDING.getCode(), OrderStatusEnum.RETURN.getCode());
        List<OrderVo> orderList = orderRepository.findAllByIds(orderIdList, statusList);
        // 按提醒时间过滤出订单
        List<OrderVo> sendMsgOrderList = orderList.stream().filter(orderVo -> LocalDate.now().compareTo(orderVo.getDeadline().minusDays(MessageSendConfig.RETURN_MSG_SEND_TIME)) >= 0).collect(Collectors.toList());
        log.info("sendMsgOrderList: {}", sendMsgOrderList);
        if (CollectionUtils.isEmpty(sendMsgOrderList)) return null;
        Map<Long, BkSendMessage> sendMessageMap = byTypeAndAndStatus.stream().collect(Collectors.toMap(BkSendMessage::getTargetId, Function.identity()));
        // 发送消息 并且修改消息状态
        List<BkSendMessage> updateSendMessageStatus = new ArrayList<>();
        for (OrderVo orderVo : sendMsgOrderList) {
            SendMessageVo sendMessageVo = remoteService.sendMessage(orderVo.getBorrowOpenid(), orderVo.getBookName(), DateUtils.dateToCNString(orderVo.getDeadline(), DateUtils.YMD_CN), MessageSendConfig.RETURN_MSG_SEND_TIME.toString(), MessageSendConfig.RETURN_MSG_SEND_CONTENT);
            BkSendMessage bkSendMessage = sendMessageMap.get(orderVo.getId());
            if (sendMessageVo.getErrcode() == 0) {
                bkSendMessage.setStatus(MessageStatusEnum.SENT_SUCCESS.getCode());
            } else {
                bkSendMessage.setStatus(MessageStatusEnum.SENT_FAIL.getCode());
            }
            bkSendMessage.setUpdatedTime(LocalDateTime.now());
            updateSendMessageStatus.add(bkSendMessage);
        }
        sendMessageRepository.saveAll(updateSendMessageStatus);
        return null;
    }

    @Override
    @Scheduled(cron = "0 * * * * ?")
    public Void sendMessageByBirthday() {
        List<BkSendMessage> byTypeAndAndStatus = sendMessageRepository.findByTypeAndStatus(SearchTypeEnum.BIRTHDAY_REMIND.getCode(), MessageStatusEnum.UN_SEND.getCode());
        if (CollectionUtils.isEmpty(byTypeAndAndStatus)) return null;
        Map<Long, BkSendMessage> sendMessageMap = byTypeAndAndStatus.stream().collect(Collectors.toMap(BkSendMessage::getTargetId, Function.identity()));
        List<Long> birthdayRemindIdList = byTypeAndAndStatus.stream().map(BkSendMessage::getTargetId).collect(Collectors.toList());
        List<BkBirthdayRemind> allById = birthdayRemindRepository.findAllById(birthdayRemindIdList);
        log.info("推送提醒列表：{}", allById);
        LocalDateTime today = LocalDateTime.now();
        for (BkBirthdayRemind bkBirthdayRemind : allById) {
            int year = bkBirthdayRemind.getRemindDate().getYear();
            int dayOfMonth = bkBirthdayRemind.getRemindDate().getDayOfMonth();
            int monthValue = bkBirthdayRemind.getRemindDate().getMonthValue();
            int hour = bkBirthdayRemind.getRemindDate().getHour();
            int minute = bkBirthdayRemind.getRemindDate().getMinute();
            if (year <= today.getYear() && monthValue <= today.getMonthValue() && dayOfMonth <= today.getDayOfMonth() && hour <= today.getHour() && minute <= today.getMinute()) {
                // 发送消息 并且修改消息状态
                List<BkSendMessage> updateSendMessageStatus = new ArrayList<>();
                Optional<User> byId = userRepository.findById(bkBirthdayRemind.getUserId());
                SendMessageVo sendMessageVo = remoteService.sendMessageByBirthdayRemind(byId.get(), bkBirthdayRemind.getName(), DateUtils.dateToString(bkBirthdayRemind.getCreatedTime(), DateUtils.YMD_CN), bkBirthdayRemind.getRemark());
                log.info("推送提醒 返回值：{}", sendMessageVo);
                BkSendMessage bkSendMessage = sendMessageMap.get(bkBirthdayRemind.getId());
                if (sendMessageVo.getErrcode() == 0) {
                    bkSendMessage.setStatus(MessageStatusEnum.SENT_SUCCESS.getCode());
                } else {
                    bkSendMessage.setStatus(MessageStatusEnum.SENT_FAIL.getCode());
                }
                bkSendMessage.setUpdatedTime(LocalDateTime.now());
                updateSendMessageStatus.add(bkSendMessage);
                sendMessageRepository.saveAll(updateSendMessageStatus);
            }
        }
        return null;
    }

}
